﻿using Newtonsoft.Json;
using PddHelper.Api;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Security.Cryptography;
using System.Text;
using System.Windows;

namespace PddHelper.Framework
{
    /// <summary>
    /// 工具类
    /// </summary>
    public class Tools
    {
        #region 写异常日志

        /// <summary>
        /// 写异常日志
        /// </summary>
        /// <param name="title"></param>
        /// <param name="log"></param>
        public static void AddErrorLog(string title, string log)
        {
            try
            {
                RestSharpPostEncrypt<dynamic>("Log/AddErrLog", new { title, log });
            }
            catch (Exception ex)
            {
            }
        }
        #endregion

        #region RestSharp Get/Post  请求

        /// <summary>
        /// 发起POST同步请求
        /// 自动加解密 主要是客户端和后台Api通讯使用
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="par">请求参数</param>
        /// <param name="headers">请求头</param> 
        /// <param name="timeout">超时时间(秒),默认20秒</param>
        /// <returns></returns>
        public static ApiRequest<T> RestSharpPostEncrypt<T>(string url, dynamic par = null, Dictionary<string, object> headers = null, int timeout = 30)
        {
            try
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
                url = $"/{url}";
                var retObj = new ApiRequest<T>() { Code = ApiStatusCode.BusinessException, Msg = "请求异常" };

                var _par = AesHelper.Encrypt(JsonConvert.SerializeObject(par));
                _par = JsonConvert.SerializeObject(new { Encrypt = _par });//加密传输 

                var client = new RestClient(url);
                var request = new RestRequest(Method.POST);
                request.Timeout = timeout * 1000;
                if (headers != null)
                {
                    foreach (var item in headers)
                    {
                        request.AddParameter(item.Key, item.Value, ParameterType.HttpHeader);
                    }
                }
                else
                {
                    headers = new Dictionary<string, object>();
                }
                //携带登录参数
                if (!string.IsNullOrEmpty(LoginUserCache.login_token))
                {
                    request.AddParameter("Token", LoginUserCache.login_token, ParameterType.HttpHeader);
                }

                request.AddParameter("application/json", _par, ParameterType.RequestBody);
                IRestResponse response = client.Execute(request);

                var ret = response.Content ?? ""; //返回的结果
                if (!string.IsNullOrEmpty(ret))
                {
                    // 创建一个 JsonSerializerSettings 对象并设置日期时间格式
                    var settings = new JsonSerializerSettings
                    {
                        DateFormatString = "yyyy-MM-dd HH:mm:ss"
                    };

                    retObj = JsonConvert.DeserializeObject<ApiRequest<T>>(ret, settings);//反序列化 解密
                    if (retObj.Code == ApiStatusCode.NoPower)//登录过期
                    {

                    }
                }
                return retObj;
            }
            catch (Exception ex)
            {
                return new ApiRequest<T>() { Code = ApiStatusCode.RequestError, Msg = ex.Message };
            }
        }

        /// <summary>
        /// 发起POST同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="headers"></param>
        /// <param name="cookies"></param>
        /// <param name="ua"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static string RestSharpPost(string url, string postData = "", Dictionary<string, string> headers = null, Dictionary<string, string> cookies = null, string ua = "", int timeout = 10)
        {
            IRestResponse response = RestSharpPost1(url, postData, headers, cookies, ua, timeout);
            var ret = response.Content ?? ""; //返回的结果
            return ret;
        }

        /// <summary>
        /// 发起POST同步请求
        /// 返回IRestResponse
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="headers"></param>
        /// <param name="cookies"></param>
        /// <param name="ua"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static IRestResponse RestSharpPost1(string url, string postData = "", Dictionary<string, string> headers = null, Dictionary<string, string> cookies = null, string ua = "", int timeout = 30)
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
            postData = postData ?? "";
            if (string.IsNullOrEmpty(ua))
            {
                ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36";
            }

            var client = new RestClient(url);
            var request = new RestRequest(Method.POST);
            request.Timeout = timeout * 1000;
            request.AddParameter("application/json", postData, ParameterType.RequestBody);

            if (headers != null)
            {
                foreach (var item in headers)
                {
                    request.AddHeader(item.Key, item.Value);
                }
            }
            //request.AddHeader("User-Agent", ua);
            client.UserAgent = ua;


            if (cookies != null)
            {
                foreach (var item in cookies)
                {
                    request.AddCookie(item.Key, item.Value);
                }
            }
            IRestResponse response = client.Execute(request);
            return response;
        }

        /// <summary>
        /// 发起get同步请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="headers"></param>
        /// <param name="cookies"></param>
        /// <param name="ua"></param>
        /// <param name="timeOut"></param>
        /// <returns></returns>
        public static string RestSharpGet(string url, Dictionary<string, string> headers = null, Dictionary<string, string> cookies = null, string ua = "", int timeOut = 30)
        {
            try
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
                if (string.IsNullOrEmpty(ua))
                {
                    ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36";
                }

                var client = new RestClient(url)
                {
                    CookieContainer = new System.Net.CookieContainer()
                };
                var request = new RestRequest(Method.GET);
                request.Timeout = timeOut * 1000;

                if (headers != null)
                {
                    foreach (var item in headers)
                    {
                        request.AddHeader(item.Key, item.Value);
                    }
                }
                request.AddHeader("Accept", "*/*");
                request.AddHeader("User-Agent", ua);

                if (cookies != null)
                {
                    foreach (var item in cookies)
                    {
                        request.AddCookie(item.Key, item.Value);
                    }
                }

                IRestResponse response = client.Execute(request);
                var temp = client.CookieContainer.GetCookies(client.BaseUrl);

                return response.Content;
            }
            catch (Exception ex)
            {
                return ex.ToString();
            }
        }

        /// <summary>
        /// 发起POST同步请求by application/x-www-form-urlencoded
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData"></param>
        /// <param name="headers"></param>
        /// <param name="ua"></param>
        /// <param name="timeout"></param>
        /// <returns></returns>
        public static string RestSharpPostByFormUrlencoded(string url, Dictionary<string, string> postData, Dictionary<string, string> headers = null, string ua = "", int timeout = 30)
        {
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
            if (string.IsNullOrEmpty(ua))
            {
                ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36";
            }
            url += $"";
            var client = new RestClient(url);
            var request = new RestRequest(Method.POST);
            request.Timeout = timeout * 1000;

            if (headers != null)
            {
                foreach (var item in headers)
                {
                    request.AddHeader(item.Key, item.Value);
                }
            }
            request.AddHeader("Accept", "*/*");
            request.AddHeader("User-Agent", ua);
            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
            foreach (var item in postData)
            {
                request.AddParameter(item.Key, item.Value);//这种写法也是对的
            }
            IRestResponse response = client.Execute(request);
            var ret = response.Content ?? ""; //返回的结果
            return ret;
        }
        #endregion

        #region 文件读写

        /// <summary>
        /// 文件锁
        /// </summary>
        public static readonly object FileLock = new object();

        /// <summary>
        /// 文件写入方法
        /// </summary>
        /// <param name="path">文件路径:相对路径</param>
        /// <param name="str">写入内容</param>
        /// <param name="append">是否追加</param>
        /// <param name="encoding">编码格式</param>
        public static void FileWrite(string path, string str, bool append = false, string encoding = "utf-8")
        {
            path = AppDomain.CurrentDomain.BaseDirectory + path;
            path = path.Replace("/", "\\").Replace("\\\\", "\\");

            string parentDirectory = Path.GetDirectoryName(path);
            if (!Directory.Exists(parentDirectory))
            {
                Directory.CreateDirectory(parentDirectory);
            }


            var code = new System.Text.UTF8Encoding(false);
            System.IO.StreamWriter sw = null;
            try
            {
                lock (FileLock)
                {
                    sw = new System.IO.StreamWriter(path, append, code);
                    sw.Write(str);
                    sw.Flush();
                }
            }
            catch
            {

            }
            finally
            {
                if (sw != null)
                {
                    sw.Close();
                    sw.Dispose();
                }
            }
        }

        /// <summary>
        /// 文件读取方法
        /// </summary>
        /// <param name="path">文件路径:绝对路径</param>
        /// <param name="encoding">编码格式</param>
        public static string FileRead(string path, string encoding = "utf-8")
        {
            path = path.Replace("/", "\\").Replace("\\\\", "\\");

            //源码是替换掉模板中的特征字符 
            Encoding code = Encoding.GetEncoding(encoding);
            System.IO.StreamReader Sr = null;

            string str = "";

            //读取
            try
            {
                Sr = new StreamReader(path, code);
                str = Sr.ReadToEnd();
            }
            catch
            {

            }
            finally
            {
                if (Sr != null)
                {
                    Sr.Close();
                    Sr.Dispose();
                }
            }
            return str;
        }

        #endregion 文件读写

        #region 写日志         

        /// <summary>
        /// 写日志
        /// </summary>
        /// <param name="log">日志内容</param>
        /// <param name="fileName">日志文件名称</param>
        public static void AddLog(string log, string fileName = "")
        {
            var path = "";
            if (string.IsNullOrEmpty(fileName))
            {
                path = $@"userdata\logs\{DateTime.Now.ToString("yyyy-MM-dd")}.log";
            }
            else
            {
                path = $@"userdata\logs\{fileName}.log";
            }

            log = $"{DateTime.Now.ToString("HH:mm:ss")} {log}\n";
            Tools.FileWrite(path, log, true);
        }
        #endregion

        #region 获取时间戳

        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalMilliseconds).ToString();
        }
        #endregion

        #region 生成随机数

        /// <summary>
        /// 生成随机数
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string GenerateRandomString(int length = 10)
        {
            const string characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
            Random random = new Random();
            char[] result = new char[length];

            for (int i = 0; i < length; i++)
            {
                result[i] = characters[random.Next(characters.Length)];
            }

            return new string(result);
        }
        #endregion

        #region  获取计算机名称

        /// <summary>
        /// 获取计算机名称
        /// </summary>
        /// <returns></returns>
        public static string GetHostName()
        {
            string computerName = Environment.MachineName;
            return computerName;
        }
        #endregion

        #region  获取IP地址

        /// <summary>
        /// 获取IP地址
        /// </summary>
        /// <returns></returns>
        public static string GetIp()
        {
            var ip = "";
            // 获取所有网络接口
            NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();

            foreach (NetworkInterface netInterface in networkInterfaces)
            {
                // 排除回环接口和虚拟接口
                if (netInterface.NetworkInterfaceType == NetworkInterfaceType.Loopback || netInterface.NetworkInterfaceType == NetworkInterfaceType.Tunnel)
                {
                    continue;
                }

                // 获取IP地址
                IPInterfaceProperties ipProperties = netInterface.GetIPProperties();
                UnicastIPAddressInformationCollection ipAddresses = ipProperties.UnicastAddresses;

                var obj = ipAddresses.Where(ex => ex.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).FirstOrDefault();
                if (obj != null)
                {
                    ip = obj.Address.ToString();
                }
            }
            return ip;
        }
        #endregion

        #region  获取mac地址

        /// <summary>
        /// 获取mac地址
        /// </summary>
        /// <returns></returns>
        public static string GetMac()
        {
            string macAddress = string.Empty;
            foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces())
            {
                // 忽略虚拟网卡等特殊网卡
                if (nic.NetworkInterfaceType == NetworkInterfaceType.Ethernet || nic.NetworkInterfaceType == NetworkInterfaceType.Wireless80211)
                {
                    macAddress = nic.GetPhysicalAddress().ToString();
                    break;
                }
            }
            return macAddress;
        }
        #endregion

        #region 获取机器唯一码

        /// <summary>
        /// 获取机器唯一码
        /// </summary>
        /// <returns></returns>
        public static string GetMachineUniqueId()
        {
            StringBuilder uniqueIdBuilder = new StringBuilder();

            uniqueIdBuilder.Append(GetHostName());
            uniqueIdBuilder.Append(GetIp());
            uniqueIdBuilder.Append(GetMac());

            // 计算哈希值
            using (SHA256 sha256 = SHA256.Create())
            {
                byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(uniqueIdBuilder.ToString()));
                StringBuilder hashBuilder = new StringBuilder();
                foreach (byte b in hashBytes)
                {
                    hashBuilder.Append(b.ToString("X2"));
                }
                return hashBuilder.ToString();
            }
        }
        #endregion

        #region Md5加密

        /// <summary>
        /// 获取字符串MD5加密字符串
        /// </summary>
        /// <param name="str">原始字符串</param>
        /// <returns>MD5加密字符串</returns>
        public static string GetMd5(string str)
        {
            var pwd = "";
            using (var md5 = MD5.Create())
            {
                var result = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
                var strResult = BitConverter.ToString(result);
                pwd = strResult.Replace("-", "");
                pwd = pwd.ToLower();
            }
            return pwd;
        }
        #endregion

        #region 判断字符串是否为全是数字

        /// <summary>
        /// 判断字符串是否为全是数字
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsAllInteger(string str)
        {
            foreach (char c in str)
            {
                if (!char.IsDigit(c))
                {
                    return false;
                }
            }

            return true;
        }
        #endregion

        #region 生成随机数

        /// <summary>
        /// 生成随机数
        /// </summary>
        /// <returns></returns>
        public static string GetOkOrError()
        {
            Random rand = new Random();
            double randomValue = rand.NextDouble(); // 生成一个 0 到 1 之间的随机小数

            if (randomValue <= 0.8)
            {
                return "成功";
            }
            else
            {
                return "失败";
            }
        }
        #endregion
    }
}
